package com.symaster.common.swing.list;

import com.symaster.common.animation.Animation;
import com.symaster.common.animation.Curve;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;

/**
 * @author yinmiao
 * @version 2023/7/23
 */
public class SmoothScrolling {
    private JPanel root_panel;
    private JPanel left_panel;
    private JPanel button_panel;

    private JScrollBar horizontal;
    private JScrollBar vertical;
    private JViewport viewport;
    private final Animation.AnimationConfig animationConfig = Animation.AnimationConfig.ofTime(90, 0, 1);
    // private final Animation.Type typeBalanced = Animation.Type.TYPE_BALANCED;
    private final Animation animation = new Animation();

    public SmoothScrolling() {
        left_panel.add(getVerticalScrollBar());
        button_panel.add(getHorizontalScrollBar());
        left_panel.setVisible(false);
        button_panel.setVisible(false);
    }

    public JScrollBar getHorizontalScrollBar() {
        if (horizontal == null) {
            horizontal = new JScrollBar(Adjustable.HORIZONTAL);
        }
        return horizontal;
    }

    public JScrollBar getVerticalScrollBar() {
        if (vertical == null) {
            vertical = new JScrollBar(Adjustable.VERTICAL);
        }
        return vertical;
    }

    public void setViewportView(Component component) {
        if (getViewport() == null) {
            setViewport(createViewport());
        }
        getViewport().setView(component);
    }

    private void setViewport(JViewport viewport) {

        JViewport old = getViewport();
        this.viewport = viewport;
        if (viewport != null) {
            root_panel.add(viewport, BorderLayout.CENTER);
        } else if (old != null) {
            root_panel.remove(old);
        }

        if (this.viewport != null) {
            this.viewport.addMouseWheelListener(new MouseWheelListener() {
                @Override
                public void mouseWheelMoved(MouseWheelEvent e) {
                    if (viewport != null) {
                        final JViewport finalViewport = viewport;

                        Rectangle bounds = finalViewport.getBounds();

                        animation.execution(Animation.Sequence.SEQUENCE_SIMULTANEOUSLY, Animation.Strategy.Stop, new Animation.AnimationListener(Curve.TYPE_BALANCED, animationConfig) {
                            @Override
                            public void handler(double factor) {
                                int v = (int) Math.round(50.0 * factor * e.getWheelRotation());
                                finalViewport.reshape(bounds.x, bounds.y - v, bounds.width, bounds.height);
                                finalViewport.getView().repaint();


                            }
                        });


                    }

                }
            });
        }

        root_panel.revalidate();
        root_panel.repaint();
    }

    private JViewport createViewport() {
        return new JViewport();
    }

    private JViewport getViewport() {
        return viewport;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("SmoothScrolling");
        SmoothScrolling smoothScrolling = new SmoothScrolling();
        JPanel jPanel = new JPanel();
        jPanel.setPreferredSize(new Dimension(900, 2000));
        jPanel.setLayout(new FlowLayout());
        for (int i = 0; i < 100; i++) {
            JLabel jLabel = new JLabel(String.valueOf(i));
            jLabel.setPreferredSize(new Dimension(900, 30));
            jPanel.add(jLabel);
        }
        smoothScrolling.setViewportView(jPanel);
        frame.setContentPane(smoothScrolling.root_panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(900, 900));
        frame.pack();
        frame.setVisible(true);
    }

    {
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        root_panel = new JPanel();
        root_panel.setLayout(new BorderLayout(0, 0));
        left_panel = new JPanel();
        left_panel.setLayout(new BorderLayout(0, 0));
        root_panel.add(left_panel, BorderLayout.EAST);
        button_panel = new JPanel();
        button_panel.setLayout(new BorderLayout(0, 0));
        root_panel.add(button_panel, BorderLayout.SOUTH);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return root_panel;
    }
}
